package com.study.flowable.springboot.service;


import com.study.flowable.springboot.entity.ApproveVO;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.common.api.FlowableObjectNotFoundException;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author sjw
 * @description
 * @date 2019-08-31 下午3:30
 */

@Service
public class WorkFlowTaskService {

    @Autowired
    private TaskService taskService;

    @Autowired
    private RepositoryService repositoryService;


    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private ProcessEngine processEngine;

    public void approve(ApproveVO approveVO) {
        taskService.complete(approveVO.getTaskId(), approveVO.getValues());
    }

    /**
     * 部署流程定义
     * addInputStream(String var1, InputStream var2);  var1必须为输入流var2的真实名称
     * 并且以 xxx.bpmn20.xml或xxx-bpmn20.xml结尾
     *
     * @param name
     * @param file
     * @return
     * @throws IOException
     */
    public String deploy(String name, MultipartFile file) throws IOException {
        System.out.println(file.getOriginalFilename());
        return repositoryService.createDeployment()
                .addInputStream(file.getOriginalFilename(), file.getInputStream())
                .deploy().getId();

    }


    /**
     * 流程列表
     *
     * @return
     */
    public List<Map> process() {
        List<ProcessDefinition> processDefinitions =
                repositoryService.createProcessDefinitionQuery().list();
        List<Map> res = new ArrayList<>();
        processDefinitions.forEach(processDefinition -> {
            Map<String, Object> map = new HashMap<>();
            map.put("Key", processDefinition.getKey());
            map.put("Category", processDefinition.getCategory());
            map.put("Name", processDefinition.getName());
            map.put("DeploymentId", processDefinition.getDeploymentId());
            map.put("Description", processDefinition.getDescription());

            res.add(map);
        });
        return res;


    }

    /**
     * 启动流程
     *
     * @param processName
     * @param variables
     * @return
     */
    public String startProcess(String processName, Map<String, Object> variables) {
        try {
            return runtimeService.startProcessInstanceByKey(processName, variables).getBusinessKey();
        } catch (FlowableObjectNotFoundException exception) {
            return "流程定义不存在： " + exception.getMessage();
        }
    }

    /**
     * 任务审批列表
     *
     * @return
     */
    public List<Map> running() {
        List<Task> taskList = taskService.createTaskQuery().list();
        List<Map> tasks = taskList.stream().map(task -> {
            Map<String, Object> taskDetial = taskService.getVariables(task.getId());
            taskDetial.put("id", task.getId());
            taskDetial.put("processInstanceId", task.getProcessInstanceId());
            return taskDetial;
        }).collect(Collectors.toList());
        return tasks;
    }

    /**
     * 导出流程图
     *
     * @param processId
     * @param httpServletResponse
     * @throws IOException
     */
    public void genProcessDiagram(String processId, HttpServletResponse httpServletResponse) throws IOException {
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();

        //流程走完的不显示图
        if (pi == null) {
            return;
        }
        Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
        //使用流程实例ID，查询正在执行的执行对象表，返回流程实例对象
        String InstanceId = task.getProcessInstanceId();
        List<Execution> executions = runtimeService
                .createExecutionQuery()
                .processInstanceId(InstanceId)
                .list();

        //得到正在执行的Activity的Id
        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();
        for (Execution exe : executions) {
            List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(ids);
        }

        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds,
                flows, engconf.getActivityFontName(), engconf.getLabelFontName(),
                engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }


}
